<template>
  <div class="chat-container">
    <div class="chat-header">
      <h2>AI 聊天助手</h2>
    </div>
    <div class="chat-messages" ref="messagesContainer">
      <div v-for="(message, index) in messages" :key="index" :class="['message', message.role]">
        <div class="message-content">
          <div v-if="message.content" v-html="formatMessage(message.content)"></div>
          <div v-else class="loading-dots">
            <span></span>
            <span></span>
            <span></span>
          </div>
        </div>
      </div>
    </div>
    <div class="chat-input">
      <el-input
        v-model="userInput"
        type="textarea"
        :rows="3"
        placeholder="请输入您的问题..."
        @keyup.ctrl.enter="sendMessage"
      />
      <div class="input-actions">
        <span class="input-tip">按 Ctrl+Enter 发送</span>
        <el-button type="primary" :disabled="!userInput.trim() || isLoading" @click="sendMessage">发送</el-button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, computed } from 'vue';
import { marked } from 'marked';
import axios from 'axios';
import { ElMessage } from 'element-plus';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';

// 配置 marked 使用 highlight.js 进行代码高亮
marked.setOptions({
  highlight: function (code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(code, { language: lang }).value;
    }
    return hljs.highlightAuto(code).value;
  },
  breaks: true
});

const userInput = ref('');
const messages = ref([]);
const isLoading = ref(false);
const messagesContainer = ref(null);
const conversationId = ref(Date.now()); // 使用时间戳作为会话ID

// 格式化消息内容，将 Markdown 转换为 HTML
const formatMessage = (content) => {
  return marked(content);
};

// 滚动到最新消息
const scrollToBottom = async () => {
  await nextTick();
  if (messagesContainer.value) {
    messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
  }
};

// 发送消息
const sendMessage = async () => {
  const message = userInput.value.trim();
  if (!message || isLoading.value) return;
  
  // 添加用户消息到消息列表
  messages.value.push({ role: 'user', content: message });
  userInput.value = '';
  scrollToBottom();
  
  // 添加一个空的 AI 消息作为加载状态
  messages.value.push({ role: 'assistant', content: '' });
  isLoading.value = true;
  
  try {
    // 创建 EventSource 连接
    const url = `http://127.0.0.1:8080/chat/openai?conversationId=${conversationId.value}&prompt=${encodeURIComponent(message)}`;
    const eventSource = new EventSource(url);
    
    let aiResponse = '';
    
    // 监听消息事件
    eventSource.onmessage = (event) => {
      if (event.data) {
        aiResponse += event.data;
        // 更新最后一条消息的内容
        messages.value[messages.value.length - 1].content = aiResponse;
        scrollToBottom();
      }
    };
    
    // 监听错误事件
    eventSource.onerror = (error) => {
      console.error('EventSource error:', error);
      eventSource.close();
      isLoading.value = false;
      
      // 如果没有收到任何响应，显示错误消息
      if (!aiResponse) {
        messages.value[messages.value.length - 1].content = '抱歉，服务器没有响应。请稍后再试。';
        ElMessage.error('连接服务器失败，请检查网络或服务器状态');
      }
    };
    
    // 监听完成事件
    eventSource.addEventListener('complete', () => {
      eventSource.close();
      isLoading.value = false;
    });
  } catch (error) {
    console.error('Error sending message:', error);
    messages.value[messages.value.length - 1].content = '发送消息时出错：' + error.message;
    isLoading.value = false;
  }
};z

// 组件挂载时添加欢迎消息
onMounted(() => {
  messages.value.push({
    role: 'assistant',
    content: '你好！我是AI助手，有什么可以帮助你的吗？'
  });
});
</script>

<style scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  box-sizing: border-box;
}

.chat-header {
  text-align: center;
  padding-bottom: 20px;
  border-bottom: 1px solid #eaeaea;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.message {
  display: flex;
  margin-bottom: 16px;
}

.message.user {
  justify-content: flex-end;
}

.message-content {
  max-width: 80%;
  padding: 12px 16px;
  border-radius: 8px;
  word-break: break-word;
}

.user .message-content {
  background-color: #ecf5ff;
  color: #303133;
  border-top-right-radius: 0;
}

.assistant .message-content {
  background-color: #f5f7fa;
  color: #303133;
  border-top-left-radius: 0;
}

.chat-input {
  margin-top: 20px;
  border-top: 1px solid #eaeaea;
  padding-top: 20px;
}

.input-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
}

.input-tip {
  color: #909399;
  font-size: 12px;
}

/* 加载动画 */
.loading-dots {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: center;
  padding: 8px;
}

.loading-dots span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #909399;
  display: inline-block;
  animation: bounce 1.4s infinite ease-in-out both;
}

.loading-dots span:nth-child(1) {
  animation-delay: -0.32s;
}

.loading-dots span:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes bounce {
  0%, 80%, 100% { 
    transform: scale(0);
  } 40% { 
    transform: scale(1.0);
  }
}

/* 代码块样式 */
:deep(pre) {
  background-color: #f6f8fa;
  border-radius: 6px;
  padding: 16px;
  overflow-x: auto;
  margin: 8px 0;
}

:deep(code) {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 14px;
}

:deep(p) {
  margin: 8px 0;
}

:deep(ul), :deep(ol) {
  padding-left: 24px;
  margin: 8px 0;
}

:deep(blockquote) {
  border-left: 4px solid #dfe2e5;
  padding-left: 16px;
  color: #6a737d;
  margin: 8px 0;
}

:deep(table) {
  border-collapse: collapse;
  width: 100%;
  margin: 8px 0;
}

:deep(th), :deep(td) {
  border: 1px solid #dfe2e5;
  padding: 8px 12px;
  text-align: left;
}

:deep(th) {
  background-color: #f6f8fa;
}
</style>
